#ifndef __SSDSIM_CACHE__
#define __SSDSIM_CACHE__
#include "ssdsim_global.h"
#include <set>
#include <queue>
#include <map>

#define CACHE_SHIFT 12
#define CACHE_ADDR(x) (x) >> CACHE_SHIFT

///////////////////////////
//////utility
#define NOT_FOUND -1
///////////////////////////
//Delay
#define CACHE_ACCESS_DELAY 0.004 ms
///////////////////////////
class Cache_info{
public:
	int lbn;
	int valid;
	int dirty;
	int age;

};
class Cache_stat{
public:
	int cache_hit;
	int cache_miss;
};
class Cache_table_entry{
public:
	int page;
	int index;
	int age;
friend bool operator < (Cache_table_entry entry1, Cache_table_entry entry2){
	return entry1.age > entry2.age;
}

};

//bool Cache_table_entry_compare(Cache_table_entry *a, Cache_table_entry *b){
//	if(a->age < b->age)
//		return true;
//	return false;
//}

class Cache_validset_entry{
	int page;
	int index;
	friend bool operator < (Cache_validset_entry entry1, Cache_validset_entry entry2){
		return entry1.page < entry1.page;
	}
};


class Cache_dev{
public:
	Cache_dev(int, FILE*);
	int is_incache(int);
	int find_lru_victim();
	int get_empty_slot();
	bool is_cache_full();
	void send_io_cache(ioreq_event *);
	void make_cache_dirty(int, int);
	void push_cache(int, int);
	void replace_victim_cache(int);
	void write_out_trace(ioreq_event*);
	void send_cache_request(ioreq_event * curr);

private:
	int cache_size;
	int curr_size;
	int current_time;
	int free_count;
	int *free_list;
	set<int> valid_set;
	map<int,int> valid_map;

	priority_queue<Cache_table_entry> LRU_queue;
	FILE *outfile;
	Cache_info **cache;
	Cache_stat *cache_stat;
};

#endif /*__SSDSIM_CACHE__*/

